package com.xlb.exception;

import com.xlb.enums.ResponseCodeEnum;
import com.xlb.utils.Response;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.nio.file.AccessDeniedException;
import java.util.Optional;

/**
 * @author 小聋包
 * @date 2024/5/14
 * @Version 1.0
 */
@ControllerAdvice
@Slf4j
public class GlobalExceptionHandler {

    private HttpServletRequest request;
    private MethodArgumentNotValidException e;

    /**
     *捕获自定义业务异常
     * @param request
     * @param e
     * @return
     */
    @ExceptionHandler({BizException.class})
    @ResponseBody
    public Response<Object> handleBizException(HttpServletRequest request, BizException e) {
        log.warn("{} request fail,errorCOde:{},errorMessage:{}",request.getRequestURI(), e.getErrorCode(), e.getErrorMessage());
        return Response.fail(e);
    }

    /**
     * 其他类型异常
     * @param request
     * @param e
     * @return
     */
    @ExceptionHandler({Exception.class})
    @ResponseBody
    public Response<Object> handleOtherException(HttpServletRequest request, Exception e) {
        log.error("{} request error",request.getRequestURI(),e);
        return Response.fail(ResponseCodeEnum.SYSTEM_ERROR);
    }

    /**
     * 捕获参数校验异常
     * @param request
     * @param e
     * @return
     */
    @ExceptionHandler({MethodArgumentNotValidException.class})
    @ResponseBody
    public Response<Object> handleMethodArgumentNotValidException(HttpServletRequest request, MethodArgumentNotValidException e) {
       //参数错误异常码
        String errorCode=ResponseCodeEnum.PARAM_NOT_VALID.getErrorCode();
        //获取BindingResult
        BindingResult bindingResult=e.getBindingResult();
        StringBuilder sb=new StringBuilder();
        //获取校验不通过的字段,并组合错误信息,格式为：email 邮箱格式不正确,当前值 ：“123qq.com";
        Optional.ofNullable(bindingResult.getFieldErrors()).ifPresent(errors->{
            errors.forEach(error->
                sb.append(error.getField())
                        .append(" ")
                        .append(error.getDefaultMessage())
                        .append(",当前值 ：“")
                        .append(error.getRejectedValue())
                        .append(";")
            );

        });
        //错误信息
        String errorMessage=sb.toString();
        log.error("{} request error,errorCode:{},errorMessage:{}",request.getRequestURI(),errorCode,errorMessage);
        return Response.fail(errorCode,errorMessage);
    }
    @ExceptionHandler({ AccessDeniedException.class })
    public void throwAccessDeniedException(AccessDeniedException e) throws AccessDeniedException {
        // 捕获到鉴权失败异常，主动抛出，交给 RestAccessDeniedHandler 去处理
        log.info("============= 捕获到 AccessDeniedException");
        throw e;
    }
}
